use std::ops::BitAnd;
use std::sync::atomic::{AtomicI32, Ordering};
use time::Instant;
use crate::test_only::num_to_bit_str;

const CONST_QUEENS_COUNT: i32 = 8;
const CONST_QUEENS_COUNT_USIZE: usize = CONST_QUEENS_COUNT as usize;

#[test]
fn test_low_bit() {
    let var_in = 44;
    println!("{}", num_to_bit_str(-var_in & var_in));
    let instant = Instant::now();
    let duration = instant.elapsed();
    println!("{}",duration);

}

#[test]
fn test_eight_queens() {
    let mut queen_list: [i32; CONST_QUEENS_COUNT_USIZE] = [0; CONST_QUEENS_COUNT_USIZE];

    // unsafe {
    put_queen(CONST_QUEENS_COUNT, queen_list, 0);
    // }
}

fn check_conflict(queen_list: &mut [i32; CONST_QUEENS_COUNT_USIZE], next_y: i32) -> bool {
    let next_y = next_y as usize;
    let next_y_int = next_y as i32;
    for position_y in 0..next_y {
        let position_y_int = position_y as i32;
        if (queen_list[position_y] - queen_list[next_y]).abs()
            == (position_y_int - next_y_int).abs()
        {
            return true;
        }

        if queen_list[position_y] == queen_list[next_y] {
            return true;
        }
    }
    return false;
}

fn join_array(arr: &[i32]) -> String {
    let mut ret: String = String::from("");
    let length = arr.len();
    for i in 0..length - 1 {
        ret = [ret, arr[i].to_string(), String::from(", ")].concat();
    }
    ret = [ret, arr[length - 1].to_string()].concat();

    return ret;
}

fn print_queen_map(arr: &[i32], line: i32) {
    let len = arr.len();
    println!("{}:{}", line, "=".repeat(len));
    let mut eachLine = String::new();
    for i in 0..len {
        for j in 0..len {
            if arr[i] == j as i32 {
                eachLine.push_str(" * ");
            } else {
                eachLine.push_str(" _ ");
            }
        }
        println!("{}", eachLine);
        eachLine.clear();
    }
}

static COUNT: AtomicI32 = AtomicI32::new(1);
fn put_queen(queens_count: i32, mut queen_list: [i32; CONST_QUEENS_COUNT_USIZE], mut next_y: i32) {
    let next_y_usize = next_y as usize;
    for i in 0..queens_count {
        queen_list[next_y_usize] = i;
        if check_conflict(&mut queen_list, next_y) == false {
            next_y = next_y + 1;
            if next_y < queens_count {
                put_queen(queens_count, queen_list, next_y)
            } else {
                print_queen_map(&queen_list, COUNT.fetch_add(1, Ordering::SeqCst));
            }
            next_y = next_y - 1;
        }
    }
}
